#include "spin_box_demo_panel.hpp"

SpinBoxDemoPanel::SpinBoxDemoPanel(bool id)
    : index(0)
{
  std::cout << "Create SpinBoxDemoPanel instance ..." << std::endl;
  if (id)
    this->initUIs();
}

SpinBoxDemoPanel::~SpinBoxDemoPanel()
{
  delete image_label;
  delete text_label;
  delete win_spinbox;
  delete sigma_spinbox;
  delete combox;
}


void SpinBoxDemoPanel::initUIs()
{
  this->image_label = new QLabel();
  this->text_label = new QLabel();

  this->win_spinbox = new QSpinBox();
  this->sigma_spinbox = new QDoubleSpinBox();

  this->combox = new QComboBox();

  this->setLayout(ORIGIN_BOX());
}

QFont SpinBoxDemoPanel::set_font()
{
  QFont font("Arial", 8, QFont::Bold);
  return font;
}

QVBoxLayout *SpinBoxDemoPanel::ORIGIN_BOX()
{
  QVBoxLayout *vbox = new QVBoxLayout();

  vbox->addWidget(PANEL_1_());
  vbox->addWidget(PANEL_2_());
  vbox->addWidget(PANEL_3_());
  IMAGE_TEST(QDir::homePath().toStdString() + "/opencv_tutorial_data/images/gaoyy.png");
  vbox->addWidget(image_label);

  vbox->addStretch(1);
  // 返回配置好的布局
  return vbox;
}

QPixmap SpinBoxDemoPanel::mat_transfer(const std::string &fileName)
{
  cv::Mat bgr = cv::imread(fileName);
  if (bgr.empty())
  {
    std::cerr << "Error loading image: " << fileName << std::endl;
    return QPixmap();
  }

  std::cout << "width:" << bgr.cols << " height:" << bgr.rows << std::endl;
  cv::Mat dst;
  cv::blur(bgr, dst, cv::Size(5, 5));
  cv::Mat image;
  cv::cvtColor(dst, image, cv::COLOR_BGR2RGB);
  QImage img = QImage(image.data, image.cols, image.rows, image.step, QImage::Format_RGB888);
  img = img.scaled(QSize(800, 600), Qt::KeepAspectRatio);
  std::cout << "width:" << img.width() << " height:" << img.height() << std::endl;

  QPixmap pixmap;
  pixmap = pixmap.fromImage(img);

  return pixmap;
}

void SpinBoxDemoPanel::TEXT_LABEL(const QString &text)
{
  text_label->setFont(set_font());
  text_label->setAlignment(Qt::AlignCenter);                                    // 当前行中心显示
  text_label->setStyleSheet("background-color: rgb(127, 255, 255);color:red;"); // CSS 样式
  text_label->setText(text);
}

void SpinBoxDemoPanel::IMAGE_TEST(const std::string &fileName)
{
  image_label->setAlignment(Qt::AlignCenter);                              // 当前行中心显示
  image_label->setStyleSheet("background-color: rgb(0, 0, 0);color:red;"); // CSS 样式
  image_label->setPixmap(mat_transfer(fileName));
}

QWidget *SpinBoxDemoPanel::PANEL_1_()
{
  QWidget *panel = new QGroupBox("图像选择");
  QHBoxLayout *hbox = new QHBoxLayout();

  hbox->addWidget(SELECT_IMAGE_BUTTON());
  TEXT_LABEL(QDir::homePath() + "/opencv_tutorial_data/images/gaoyy.png");
  hbox->addWidget(text_label);
  hbox->addStretch(1);

  panel->setLayout(hbox);

  return panel;
}

QWidget *SpinBoxDemoPanel::PANEL_2_()
{
  QWidget *panel = new QGroupBox("去噪算法");
  QHBoxLayout *hbox = new QHBoxLayout();
  win_spinbox->setRange(0, 100);
  sigma_spinbox->setRange(0, 100);
  combox->addItem("中值模糊");
  combox->addItem("高斯模糊");
  combox->addItem("盒子模糊");
  hbox->addWidget(new QLabel("模糊方法："));
  hbox->addWidget(combox);
  hbox->addStretch(1);
  hbox->addWidget(new QLabel("窗口："));
  hbox->addWidget(win_spinbox);
  hbox->addStretch(1);
  hbox->addWidget(new QLabel("方差："));
  hbox->addWidget(sigma_spinbox);
  panel->setLayout(hbox);

  return panel;
}

QWidget *SpinBoxDemoPanel::PANEL_3_()
{
  QWidget *panel = new QWidget();
  QHBoxLayout *hbox = new QHBoxLayout();

  hbox->addStretch(1);
  hbox->addWidget(DO_DENOISE_PROCESS_BUTTON());
  panel->setLayout(hbox);

  return panel;
}

QPushButton* SpinBoxDemoPanel::SELECT_IMAGE_BUTTON()
{
  auto selectBtn = new QPushButton();
  selectBtn->setText("Select");
  this->ADD_SELECT_IMAGE_SLOTS(selectBtn);
  return selectBtn;
}

QPushButton* SpinBoxDemoPanel::DO_DENOISE_PROCESS_BUTTON()
{
  auto applyBtn = new QPushButton();
  applyBtn->setText("运行");
  this->ADD_DO_DENOISE_PROCESS_SLOTS(applyBtn);
  return applyBtn;
}

void SpinBoxDemoPanel::ADD_SELECT_IMAGE_SLOTS(QPushButton *selectBtn)
{
  connect(selectBtn, &QPushButton::clicked, this, &SpinBoxDemoPanel::SELECT_IMAGE);
}

void SpinBoxDemoPanel::ADD_DO_DENOISE_PROCESS_SLOTS(QPushButton *applyBtn)
{
  connect(applyBtn, &QRadioButton::clicked, this, &SpinBoxDemoPanel::DO_DENOISE_PROCESS);
}

void SpinBoxDemoPanel::SELECT_IMAGE()
{
  std::cout << "SELECT_IMAGE button clicked ..." << std::endl;
  auto fileName = QFileDialog::getOpenFileName(this, "Open Image", QDir::homePath() + "/opencv_tutorial_data/images", tr("*.jpg *.png"));
  if (fileName.isEmpty())
    return;

  this->text_label->setText(fileName);
  DO_DENOISE_PROCESS();
}

void SpinBoxDemoPanel::DO_DENOISE_PROCESS()
{
  std::cout << "DO_DENOISE_PROCESS button clicked ..." << std::endl;
  std::string file_path = this->text_label->text().toStdString();
  cv::Mat src = cv::imread(file_path);
  if (src.empty())
  {
    std::cerr << "Error loading image: " << file_path << std::endl;
    return;
  }

  cv::Mat dst;
  int index = combox->currentIndex();
  int ws = this->win_spinbox->value();
  int wsize = 2*ws + 1; // 以下三个窗口参数必须式奇数
  double sigma = this->sigma_spinbox->value();

  int64 st, et;
  float t;

  switch (index)
  {
  case 1:
  {
    if (ws == 0) wsize = 0;
    st = cv::getTickCount();
    cv::GaussianBlur(src, dst, cv::Size(wsize, wsize), sigma);
    et = cv::getTickCount() - st;
    cv::putText(dst, "GaussianBlur:", cv::Point(10, 100), cv::FONT_HERSHEY_PLAIN, 3.0, cv::Scalar(0, 255, 0), 3);
    break;
  }
  case 2:
  {
    st = cv::getTickCount();
    cv::boxFilter(src, dst, -1, cv::Size(wsize, wsize));
    et = cv::getTickCount() - st;
    cv::putText(dst, "boxFilter:", cv::Point(10, 100), cv::FONT_HERSHEY_PLAIN, 3.0, cv::Scalar(0, 255, 0), 3);
    break;
  }
  default:
    st = cv::getTickCount();
    cv::medianBlur(src, dst, wsize);
    et = cv::getTickCount() - st;
    cv::putText(dst, "medianBlur:", cv::Point(10, 100), cv::FONT_HERSHEY_PLAIN, 3.0, cv::Scalar(0, 255, 0), 3);
    break;
  }

  t = et / cv::getTickFrequency();
  cv::putText(dst, cv::format("%.5f ms", t), cv::Point(400, 100), cv::FONT_HERSHEY_PLAIN, 3.0, cv::Scalar(0, 255, 0), 3);

  cv::Mat image;
  cv::cvtColor(dst, image, cv::COLOR_BGR2RGB);
  QImage img = QImage(image.data, image.cols, image.rows, image.step, QImage::Format_RGB888);
  img = img.scaled(QSize(800, 600), Qt::KeepAspectRatio);

  this->image_label->setPixmap(QPixmap::fromImage(img));
}
